package util

import (
	"bytes"
	"encoding/json"
	//"fmt"
	"time"

	"github.com/astaxie/beego"
	"github.com/garyburd/redigo/redis"
)

var (
	pool        *redis.Pool
	redisServer string
	redisPass   string
	maxIdle     int
	maxActive   int
)

func initPool() error {
	redisServer = beego.AppConfig.String("redisurls")
	redisPass = beego.AppConfig.String("redispass")
	maxIdle, _ = beego.AppConfig.Int("maxIdle")
	maxActive, _ = beego.AppConfig.Int("maxActive")
	pool = &redis.Pool{
		MaxIdle:     maxIdle,
		MaxActive:   maxActive,
		IdleTimeout: (60 * time.Second),
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", redisServer)
			if err != nil {
				return nil, err
			}
			if _, err := c.Do("AUTH", redisPass); err != nil {
				c.Close()
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			if time.Since(t) < time.Minute {
				return nil
			}
			_, err := c.Do("PING")
			return err
		},
	}
	_, err := pool.Dial()
	if err != nil {
		return err
	} else {
		return nil
	}
}

func Get(key string) (interface{}, error) {
	if pool == nil {
		err := initPool()
		if err != nil {
			return nil, err
		}
	}
	c := pool.Get()
	defer c.Close()
	res, err := c.Do("get", key)
	if err != nil {
		return nil, err
	}
	var r interface{}
	if res != nil {
		decoder := json.NewDecoder(bytes.NewReader(res.([]byte)))
		if err := decoder.Decode(&r); err != nil {
			return nil, err
		}
	}
	return r, nil
}

func Set(key string, value interface{}) error {
	if pool == nil {
		err := initPool()
		if err != nil {
			return err
		}
	}
	c := pool.Get()
	defer c.Close()
	v, _ := json.Marshal(value)
	_, err := c.Do("set", key, v)
	if err != nil {
		return err
	}
	c.Do("expire", key, 10)
	return nil
}
func GetInt(key string) (int, error) {
	if pool == nil {
		err := initPool()
		if err != nil {
			return 0, err
		}
	}
	c := pool.Get()
	defer c.Close()
	result, err := redis.Int(c.Do("get", key))
	return result, err
}
func Do(name string, args ...interface{}) (interface{}, error) {
	if pool == nil {
		err := initPool()
		if err != nil {
			return 0, err
		}
	}
	c := pool.Get()
	defer c.Close()
	if len(args) == 1 {
		result, err := c.Do(name, args[0])
		return result, err
	} else {
		result, err := c.Do(name, args[0], args[1])
		return result, err
	}

}
